home *** CD-ROM | disk | FTP | other *** search
/ Enter 2006 September / Enter 09 2006.iso / Internet / SpamExperts Home 1.1 / SpamExperts Home.exe / lib / spamexperts.modules / spamexperts / fingerprint / fingerprint.pyc (.txt) < prev   
Encoding:
Python Compiled Bytecode  |  2006-07-14  |  5.8 KB  |  168 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.4)
  3.  
  4. '''E-mail fingerprint extraction library
  5.  
  6. Client interface to fingerprint database needed for centralized
  7. ham/spam recognition.
  8. '''
  9. from __future__ import division
  10. import re
  11. import sys
  12. import types
  13.  
  14. try:
  15.     set
  16. except NameError:
  17.     from sets import Set as set
  18.  
  19. from spambayes import tokenizer
  20. from spamexperts.Options import options
  21.  
  22. class Fingerprint(object):
  23.     """This class is a factory for generating fingerprints from messages.
  24.  
  25.     As much as possible, text that has been added to a message to prevent
  26.     fingerprint-type schemes (random text, whitespace, HTML) is removed
  27.     before fingerprinting.
  28.  
  29.     To use, call Fingerprint.get_fingerprint() to get the fingerprint (to
  30.     pass to the server as a query), and then Fingerprint.spamprob() with
  31.     the query results to get a probability that the messages is spam.
  32.  
  33.     NOTE: fingerprint generation method is described in:
  34.       Feng Zhou, Li Zhuang, Ben Y. Zhao, Ling Huang, Anthony D. Joseph,
  35.       and John Kubiatowics. 'Approximate Object Location and Spam Filtering
  36.       on Peer-to-Peer Systems'. Appears in Proc. of ACM/IFIP/USENIX
  37.       Intl. Middleware Conf. (Middleware 2003).
  38.     """
  39.     
  40.     def get_ridges(self, data, normalise):
  41.         if normalise:
  42.             data = self.normalise(data)
  43.         
  44.         L = options[('fingerprint', 'l')]
  45.         data_length = len(data)
  46.         if data_length < L:
  47.             return [
  48.                 self._hash(data)]
  49.         
  50.         return [ self._hash(data[i:i + L]) for i in xrange(0, data_length, L) ]
  51.  
  52.     
  53.     def _hash(chunk):
  54.         '''Generate substrings, and hash them (converting to strings, and
  55.         reversing).
  56.         '''
  57.         return str(abs(hash(chunk)))[::-1]
  58.  
  59.     _hash = staticmethod(_hash)
  60.     
  61.     def check_ridges(self, data, normalise, ridges):
  62.         L = options[('fingerprint', 'l')]
  63.         if normalise:
  64.             data = data.get_payload()
  65.         else:
  66.             return []
  67.         return [ (orig, self._hash(norm) in ridges) for orig, norm in self.split_and_norm(data, L) ]
  68.  
  69.     
  70.     def split_and_norm(cls, data, required_length):
  71.         orig_chunk = []
  72.         norm_chunk = []
  73.         in_a_row = False
  74.         for c in data:
  75.             orig_chunk.append(c)
  76.             norm = cls.replace_re.sub(' ', c)
  77.             if norm != ' ' or not in_a_row:
  78.                 norm_chunk.append(norm)
  79.                 if len(norm_chunk) == required_length:
  80.                     yield (''.join(orig_chunk), ''.join(norm_chunk))
  81.                     orig_chunk = []
  82.                     norm_chunk = []
  83.                 
  84.                 if norm != ' ':
  85.                     in_a_row = False
  86.                 else:
  87.                     in_a_row = True
  88.             norm != ' '
  89.         
  90.         yield (''.join(orig_chunk), ''.join(norm_chunk))
  91.  
  92.     split_and_norm = classmethod(split_and_norm)
  93.     replace_re = re.compile('\\s+')
  94.     tokenizer = tokenizer.Tokenizer()
  95.     
  96.     def normalise(self, msg):
  97.         if options[('fingerprint', 'use_tokenizer')]:
  98.             return ' '.join(self.tokenizer.tokenize_body(msg))
  99.         
  100.         return self.replace_re.sub(' ', msg.get_payload())
  101.  
  102.     
  103.     def get_body(self, msg):
  104.         '''To get the body, we walk through the message, collecting all
  105.         parts (not just text, although only text parts are normalised).
  106.         '''
  107.         yield (msg.get('Subject', ''), False)
  108.         for part in msg.walk():
  109.             if part.get_content_maintype() == 'text':
  110.                 yield (part, True)
  111.                 continue
  112.             payload = part.get_payload()
  113.             if not isinstance(payload, types.ListType):
  114.                 yield (payload, False)
  115.                 continue
  116.         
  117.  
  118.     
  119.     def get_fingerprint(self, msg):
  120.         '''Generation of a fingerprint from an email message.
  121.  
  122.         The L parameter defines the length of collected the substrings.
  123.         The N parameter defines the number of selected substrings.
  124.         '''
  125.         hash_substrings = []
  126.         for section, normalise in self.get_body(msg):
  127.             hash_substrings.extend(self.get_ridges(section, normalise))
  128.         
  129.         hash_substrings.sort()
  130.         hash_substrings = hash_substrings[:options[('fingerprint', 'max-n')]]
  131.         cfv = set(hash_substrings)
  132.         if '' in cfv:
  133.             cfv.remove('')
  134.         
  135.         if len(cfv) < options[('fingerprint', 'min-n')]:
  136.             return set()
  137.         
  138.         return cfv
  139.  
  140.     
  141.     def notate_fingerprint(self, msg, ridges):
  142.         '''Returns a list of (data, matched).  The idea is to then draw
  143.         the message and change the colour if matched is True.'''
  144.         notated = []
  145.         for section, normalise in self.get_body(msg):
  146.             notated.extend(self.check_ridges(section, normalise, ridges))
  147.         
  148.         return notated
  149.  
  150.     
  151.     def spamprob(self, max_match_count, mail_fingerprints):
  152.         '''
  153.         Returns the spam probability for given message to be spam,
  154.         given the number of fingerprints that were matched.
  155.         '''
  156.         total_count = len(mail_fingerprints)
  157.         matching_count = int(max_match_count)
  158.         if options[('globals', 'verbose')]:
  159.             print >>sys.stderr, 'Fingerprint: Found %s matching hashes of %s total hashes' % (matching_count, total_count)
  160.         
  161.         if total_count != 0:
  162.             f_prob = 0.5 + matching_count / total_count / 2
  163.         else:
  164.             f_prob = 0.5
  165.         return f_prob
  166.  
  167.  
  168.